package com.lc1993929.shiro.bean;

import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

import java.sql.*;
import java.util.HashSet;
import java.util.Set;

/**
 * Created by LiuChang on 2017/5/18.
 * Realm    需要查询数据库，并且得到正确的数据
 */
public class SecondRealm extends AuthorizingRealm {
    /**
     * 1、doGetAuthenticationInfo    获取认证消息，如果数据库中没有数据，返回null，如果得到正确的用户名和密码，返回指定类型的对象
     * 2、AuthenticationInfo     可以使用SimpleAuthenticationInfo实现类，封装正确的用户名和密码
     * 3、authenticationToken   就是我们需要认证的token
     */
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("the second realm is working!!!");

        SimpleAuthenticationInfo info = null;
        //1、将token转换成UserPasswordToken
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) authenticationToken;
        //2、获取用户名即可
        String username = usernamePasswordToken.getUsername();
        //3、查询数据库,是否存在指定用户名和密码的用户
        try {
            Class.forName("com.mysql.jdbc.Driver");
            Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/shiro?useUnicode=true&amp;characterEncoding=UTF-8&amp;allowMultiQueries=true", "root", "root");
            PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM account WHERE name=?");
            preparedStatement.setString(1, username);
            ResultSet resultSet = preparedStatement.executeQuery();
            if (resultSet.next()) {
                //4、如果查询到了，封装查询结果，返回给我们的调用
                Object principal = username;
                Object credentials = resultSet.getString(3);
                String realmName = this.getName();
                ByteSource salt = ByteSource.Util.bytes(username);

                SimpleHash simpleHash = new SimpleHash("SHA1", credentials, salt, 1024);

                //info = new SimpleAuthenticationInfo(principal, simpleHash, realmName);
                info = new SimpleAuthenticationInfo(principal, simpleHash, salt, realmName);
            } else {
                //5、如果没有查询到，抛出一个异常
                throw new AuthenticationException();
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return info;
    }

    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //返回值：AuthorizationInfo     封装获取的用户对应的所有角色，SimpleAuthorizationInfo（Set<string>)
        //参数列表：PrincipalCollection      登陆的身份，登陆的用户名

        SimpleAuthorizationInfo info = null;
        String username = principalCollection.toString();
        try {
            Class.forName("com.mysql.jdbc.Driver");
            Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/shiro?useUnicode=true&amp;characterEncoding=UTF-8&amp;allowMultiQueries=true", "root", "root");
            PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM account WHERE name=?");
            preparedStatement.setString(1, username);
            ResultSet resultSet = preparedStatement.executeQuery();
            if (resultSet.next()) {
                //4、如果查询到了，封装查询结果，返回给我们的调用
                Object principal = username;
                Object credentials = resultSet.getString(3);
                String realmName = this.getName();
                ByteSource salt = ByteSource.Util.bytes(username);

                SimpleHash simpleHash = new SimpleHash("SHA1", credentials, salt, 1024);

                Set<String> roles = new HashSet<String>();
                roles.add(resultSet.getString(4));
                info = new SimpleAuthorizationInfo(roles);
            } else {
                //5、如果没有查询到，抛出一个异常
                throw new AuthenticationException();
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return info;
    }
}
